package cache

import (
	"time"

	"gitee.com/gousing/cache/storage"
	"gitee.com/gousing/values"
)

// GetTime 获取 time.Time 类型的缓存值, 如果不存在或已经过期则返回false
//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 Server/Local 时区
//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 Server/Local 时区
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTime(key string) time.Time {
	val, _ := GetTimeE(key)
	return val
}

// GetTimeD 获取 time.Time 型的缓存值, 如果不存在或已经过期则返回指定的 defaultVal 默认值
//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 Server/Local 时区
//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 Server/Local 时区
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeD(key string, defaultVal time.Time) time.Time {
	val, err := GetTimeE(key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetTimeE 获取 time.Time 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 Server/Local 时区
//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 Server/Local 时区
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeE(key string) (time.Time, error) {
	if key == "" {
		return time.Time{}, storage.ErrKeyIsEmpty
	}
	var val time.Time
	err := GetDefault().Scan(key, &val)
	return val, err
}

// GetTimeWith 获取指定的时区 time.Time 类型的缓存值, 如果不存在或已经过期则返回false
//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 location 指定的时区
//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 location 指定的时区
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeWith(key string, location *time.Location) (time.Time, error) {
	if key == "" {
		return time.Time{}, storage.ErrKeyIsEmpty
	}
	// 获取Any缓存值通过values进行类型转换
	anyVal, err := GetDefault().Get(key)
	if err != nil {
		return time.Time{}, err
	}
	return values.ToTimeWith(anyVal, location)
}

// GetTimeDuration 获取 time.Duration 类型的缓存值, 如果不存在或已经过期则返回false
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeDuration(key string) time.Duration {
	val, _ := GetTimeDurationE(key)
	return val
}

// GetTimeDurationD 获取 time.Duration 型的缓存值, 如果不存在或已经过期则返回指定的 defaultVal 默认值
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeDurationD(key string, defaultVal time.Duration) time.Duration {
	val, err := GetTimeDurationE(key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetTimeE 获取 time.Duration 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeDurationE(key string) (time.Duration, error) {
	if key == "" {
		return 0, storage.ErrKeyIsEmpty
	}
	var val time.Duration
	err := GetDefault().Scan(key, &val)
	return val, err
}

// GetTimeMonth 获取 time.Month 类型的缓存值, 如果不存在或已经过期则返回false
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeMonth(key string) time.Month {
	val, _ := GetTimeMonthE(key)
	return val
}

// GetTimeMonthD 获取 time.Month 型的缓存值, 如果不存在或已经过期则返回指定的 defaultVal 默认值
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeMonthD(key string, defaultVal time.Month) time.Month {
	val, err := GetTimeMonthE(key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetTimeMonthE 获取 time.Month 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeMonthE(key string) (time.Month, error) {
	if key == "" {
		return 0, storage.ErrKeyIsEmpty
	}
	var val time.Month
	err := GetDefault().Scan(key, &val)
	return val, err
}

// GetTimeWeekday 获取 time.Weekday 类型的缓存值, 如果不存在或已经过期则返回false
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeWeekday(key string) time.Weekday {
	val, _ := GetTimeWeekdayE(key)
	return val
}

// GetTimeWeekdayD 获取 time.Weekday 型的缓存值, 如果不存在或已经过期则返回指定的 defaultVal 默认值
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeWeekdayD(key string, defaultVal time.Weekday) time.Weekday {
	val, err := GetTimeWeekdayE(key)
	if err != nil {
		return defaultVal
	}
	return val
}

// GetTimeWeekdayE 获取 time.Weekday 类型的缓存值, 如果不存在或已经过期则返回空值和错误信息
//   - 支持自动转换类型: string, intX, uintX, floatX 以及实现了 values.Timer 适配接口的类型
func GetTimeWeekdayE(key string) (time.Weekday, error) {
	if key == "" {
		return 0, storage.ErrKeyIsEmpty
	}
	var val time.Weekday
	err := GetDefault().Scan(key, &val)
	return val, err
}
